package cn.kzgg.ymcc.service.impl;

import cn.kzgg.ymcc.domain.KillActivity;
import cn.kzgg.ymcc.domain.KillCourse;
import cn.kzgg.ymcc.mapper.KillActivityMapper;
import cn.kzgg.ymcc.service.IKillActivityService;
import cn.kzgg.ymcc.service.IKillCourseService;
import cn.kzgg.ymcc.util.AssertUtil;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author kzgg
 * @since 2022-08-04
 */
@Service
@Slf4j
public class KillActivityServiceImpl extends ServiceImpl<KillActivityMapper, KillActivity> implements IKillActivityService {

    @Autowired
    private IKillCourseService killCourseService;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    /**
     * 秒杀活动发布
     * <p>
     * 1.查询出秒杀活动对应的课程
     * 2.校验时间是否满足，满足条件才发布活动
     * 3.将活动下面的所有课程存储redis  怎么存？
     * 4.redis 中设置每一个秒杀课程对应的库存 -- 信号量
     * 5.结束
     *
     * @param activityId
     */
    @Override
    public void publish(Long activityId) {
        Date now = new Date();
        //1.查询出秒杀活动对应的课程(可以把活动查出来更好)
        List<KillCourse> killCourses = queryActivityCourse(activityId);
        //2.校验时间是否满足，满足条件才发布活动
        KillCourse killCourse = killCourses.get(0);
        boolean before = now.before(killCourse.getEndTime());
        AssertUtil.isTrue(before, "已过秒杀时间,不能上架");
        //3.将活动下面的所有课程存储redis
        killCourses.forEach(course -> {
            //获取key
            String key = activityId + ":" + course.getId();
            //4.设置每一个秒杀课程对应的库存 -- 信号量
            RSemaphore semaphore = redissonClient.getSemaphore(key);
            boolean setPermits = semaphore.trySetPermits(course.getKillCount());
            //5.如果设置成功就存到redis
            if (setPermits) {
                log.info("成功设置信号量,添加秒杀成功{}", course);
                //加个前缀activity后面在使用key查询的时候也加前缀好查询
                redisTemplate.opsForHash().put("activity:"+activityId, course.getId().toString(), course);
                //修改状态
                course.setPublishStatus(1);
                course.setPublishTime(now);
                killCourseService.updateById(course);
            } else {
                log.info("添加秒杀失败{}", course);
            }

        });
        //6.结束,活动状态修改
        KillActivity killActivity = selectById(activityId);
        killActivity.setPublishStatus(1);
        killActivity.setPublishTime(now);
        updateById(killActivity);
    }

    /**
     * 查询出秒杀活动对应的课程
     *
     * @param activityId
     * @return
     */
    private List<KillCourse> queryActivityCourse(Long activityId) {
        Wrapper<KillCourse> wrapper = new EntityWrapper<>();
        wrapper.eq("activity_id", activityId);
        return killCourseService.selectList(wrapper);
    }
}
